package net.wanho.shiro;

import net.wanho.entity.Perms;
import net.wanho.entity.Role;
import net.wanho.entity.User;
import net.wanho.service.PermsService;
import net.wanho.service.RoleService;
import net.wanho.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Author：汤小洋
 * Date：2023-10-11 16:09
 * Description：<描述>
 */
public class ShiroRealm extends AuthorizingRealm {

    @Resource
    private UserService userService;
    @Resource
    private RoleService roleService;
    @Resource
    private PermsService permsService;

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 首先判断用户名是否存在！
        String username = (String) authenticationToken.getPrincipal(); // 获取用户名

        User user = userService.findByUsername(username);// 根据用户名查询用户信息
        if (ObjectUtils.isEmpty(user)) {
            throw new UnknownAccountException("用户不存在！"); // 用户名不存在
        }

        // 返回SimpleAuthenticationInfo，然后交由凭证匹配器（CredentialMatcher）进行凭证的判断，默认就是对密码进行判断
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                user.getUsername(), // 用户信息
                user.getPassword(), // 密码
                ByteSource.Util.bytes(user.getSalt()), // 盐值
                getName() // Realm名称
        );
        return info;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();

        // 获取角色信息
        List<Role> roleList =  roleService.findByUsername(username);
        List<String> roles = roleList.stream()
                .map(Role::getName)
                .collect(Collectors.toList());

        // 获取权限信息
        List<String> perms = roleList.stream().flatMap(role -> { // flatMap：将多个流合并成一个流
            List<Perms> permsList = permsService.findByRoleId(role.getId());
            return permsList.stream().map(Perms::getName);
        }).collect(Collectors.toList());


        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roles);
        info.addStringPermissions(perms);
        return info;
    }

}
